home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 22 / Cream of the Crop 22.iso / os2 / bltc127.zip / BLTXMPLS.ZIP / B2_XUPD.C < prev    next >
Text File  |  1995-02-08  |  18KB  |  445 lines

  1.  
  2.  
  3. #include <os2.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7.  
  8. /* if 16-bit program, use:
  9.  *   #define __Bullet16
  10.  *   #include "bullet2.h
  11.  * otherwise (32-bit), do as below
  12.  */
  13.  
  14. #include "bullet2.h"
  15. #define BULLET BULLET32   /* if 32-bit main(), go through BULLET32 */
  16.  
  17. /* b2_xupd.c showing:
  18.  *  1) DBF create
  19.  *  2) index create x 2
  20.  *  3) inserting into the database via InsertXB, updating entire database
  21.  *  4) accessing the database with either index via GetFirst/Next/EqualXB
  22.  *  5) updating the database via UpdateXB
  23.  */
  24.  
  25. #pragma pack(1)
  26.  
  27. struct InitPack IP;
  28. struct ExitPack EP;
  29. struct FieldDescType fieldList[5];  /* 5 since 5 fields used in AnyRecType */
  30. struct CreateDataPack CDP;
  31. struct CreateKeyPack CKP;
  32. struct OpenPack OP;
  33. struct HandlePack HP;
  34. struct AccessPack AP[2];  /* 2 since 2 "linked" index files used */
  35. struct DosFilePack DFP;
  36.  
  37. struct AnyRecType {
  38.  char  tag;               /* tag not formal field but required */
  39.  char  employeeNumber[6];
  40.  char  lastName[20];
  41.  char  firstName[20];
  42.  char  SSN[10];
  43.  char  andSoOn[7];
  44. };
  45. struct AnyRecType dataRec; /* 5 fields, 64-byte record */
  46.  
  47. #pragma pack()
  48.  
  49. int     rez;
  50. int     rez2;
  51. USHORT  handleData;
  52. USHORT  handleIndex0;
  53. USHORT  handleIndex1;
  54.  
  55. char tmpStr[129];
  56. char empData[] = "$EMPDATA.DBF";
  57. char empIX0[] = "$EMPDATA.IX0";
  58. char empIX1[] = "$EMPDATA.IX1";
  59. char keyExpression0[] = "EMP_NO";
  60. char keyExpression1[] = "SUBSTR(LNAME,1,5)+SUBSTR(FNAME,1,1)+SUBSTR(SSN,6,4)";
  61. char keyBuffer[64];
  62.  
  63. int main()
  64. {
  65.  
  66. setbuf(stdout,NULL);
  67.  
  68. /* this example presumes a known record layout -- also possible is
  69.    to create the record layout on-the-fly (see [TBD].C) */
  70.  
  71. /* build the field list of the data file -- it must match byte-for-byte
  72.    AnyRecType, but structure names do not need to match actual field names */
  73.  
  74. memset(fieldList,0,sizeof(fieldList));      /* clear out all fields */
  75. strcpy(fieldList[0].fieldName, "EMP_NO");
  76. fieldList[0].fieldType = 'N';               /* stored in DBF as ASCII numbers */
  77. fieldList[0].fieldLen = 6;                  /* must match record structure */
  78. fieldList[0].fieldDC = 0;                   /* no decimal point */
  79. strcpy(fieldList[1].fieldName, "LNAME");
  80. fieldList[1].fieldType = 'C';
  81. fieldList[1].fieldLen = 20;
  82. fieldList[1].fieldDC = 0;
  83. strcpy(fieldList[2].fieldName, "FNAME");
  84. fieldList[2].fieldType = 'C';
  85. fieldList[2].fieldLen = 20;
  86. fieldList[2].fieldDC = 0;
  87. strcpy(fieldList[3].fieldName, "SSN");
  88. fieldList[3].fieldType = 'C';           /* C so we can use SUBSTR() */
  89. fieldList[3].fieldLen = 10;             /* 9 +1 for \0  (see below) */
  90. fieldList[3].fieldDC = 0;
  91. strcpy(fieldList[4].fieldName, "ETC");
  92. fieldList[4].fieldType = 'C';
  93. fieldList[4].fieldLen = 7;
  94. fieldList[4].fieldDC = 0;
  95.  
  96. /* must do InitXB before any other Bullet routine */
  97.  
  98. IP.func = INITXB;
  99. IP.JFTmode = 1;         /* allow up to 250 files open */
  100. rez = BULLET(&IP);
  101. if (rez==0) {
  102.  
  103.    EP.func = ATEXITXB;
  104.    rez = BULLET(&EP);
  105.    if (rez!=0) 
  106.       puts("bleep! DosExitList() must be full.  Continuing.\n");
  107.  
  108.  
  109.    /* delete any current files used by this program -- 
  110.       Bullet won't create a file if it already exists 
  111.       (DOS error 110 is returned on attempts to) */
  112.  
  113.    DFP.func = DELETEFILEDOS;
  114.    DFP.filenamePtr = empData;
  115.    rez = BULLET(&DFP);  /* ignore not found errors */
  116.    DFP.filenamePtr = empIX0;
  117.    rez = BULLET(&DFP);
  118.    DFP.filenamePtr = empIX1;
  119.    rez = BULLET(&DFP);
  120.  
  121.    CDP.func = CREATEDXB;
  122.    CDP.filenamePtr = empData;
  123.    CDP.noFields = 5;
  124.    CDP.fieldListPtr = fieldList;
  125.    CDP.fileID = 3;                /* standard DBF file ID byte */
  126.    rez = BULLET(&CDP);
  127.    if (rez==0) {
  128.  
  129.       OP.func = OPENDXB;
  130.       OP.filenamePtr = empData;
  131.       OP.asMode = READWRITE | DENYNONE;
  132.       rez = BULLET(&OP);
  133.       if (rez==0) {
  134.  
  135.          handleData = OP.handle;
  136.          CKP.func = CREATEKXB;
  137.          CKP.filenamePtr = empIX0;
  138.          CKP.keyExpPtr = keyExpression0;
  139.          CKP.xbLink = handleData;
  140.          CKP.keyFlags = cLONG | cUNIQUE; /* 32-bit binary key */
  141.          CKP.codePageID = -1;            /* eventhough data field is ASCII */
  142.          CKP.countryCode = -1;
  143.          CKP.collatePtr = NULL;
  144.          rez = BULLET(&CKP);
  145.          if (rez==0) {
  146.  
  147.             CKP.func = CREATEKXB;
  148.             CKP.filenamePtr = empIX1;
  149.             CKP.keyExpPtr = keyExpression1;
  150.             CKP.xbLink = handleData;
  151.             CKP.keyFlags = cCHAR | cUNIQUE;  /* character key */
  152.             CKP.codePageID = -1;
  153.             CKP.countryCode = -1;
  154.             CKP.collatePtr = NULL;
  155.             rez = BULLET(&CKP);
  156.             if (rez==0) {
  157.  
  158.                OP.func = OPENKXB;
  159.                OP.filenamePtr = empIX0;
  160.                OP.asMode = READWRITE | DENYNONE;
  161.                OP.xbLink = handleData;
  162.                rez = BULLET(&OP);
  163.                if (rez==0) {
  164.  
  165.                   handleIndex0 = OP.handle;
  166.  
  167.                   OP.func = OPENKXB;
  168.                   OP.filenamePtr = empIX1;
  169.                   OP.asMode = READWRITE | DENYNONE;
  170.                   OP.xbLink = handleData;
  171.                   rez = BULLET(&OP);
  172.                   if (rez==0) {
  173.  
  174.                      handleIndex1 = OP.handle;
  175.  
  176. /* AT THIS POINT, we have created the single DBF data file and its two
  177.    related index files, and opened them, ready for work */
  178.  
  179.                      dataRec.tag = ' ';     /* set to "not deleted" */
  180.  
  181. /* note the use of strncpy() -- we don't want \0 involved since this field is
  182.    of type N and so should be right-aligned, ASCII (for DBF compatibility) */
  183.  
  184.                      strncpy(dataRec.employeeNumber,"     1",6);
  185.  
  186. /* since these fields are C type, they can be treated as regular strings with
  187.    \0 appended -- SSN is being used as a C type field, and so its size was made
  188.    to be 10 bytes; you could use strncpy() on SSN and change it to SSN[9]... */
  189.  
  190.                      strcpy(dataRec.lastName,"Huth");
  191.                      strcpy(dataRec.firstName,"Cornel");
  192.                      strcpy(dataRec.SSN,"123456789");
  193.                      strcpy(dataRec.andSoOn,"abc21_");
  194.  
  195. /* record has been built, add it to DBF and insert its keys into index files */
  196.  
  197.                      AP[0].func = INSERTXB;
  198.                      AP[0].handle = handleIndex0;
  199.                      AP[0].recPtr = &dataRec;
  200.                      AP[0].keyPtr = keyBuffer;
  201.                      AP[0].nextPtr = &AP[1];
  202.                      AP[1].func = INSERTXB;
  203.                      AP[1].handle = handleIndex1;
  204.                      AP[1].recPtr = &dataRec;
  205.                      AP[1].keyPtr = keyBuffer;
  206.                      AP[1].nextPtr = NULL;
  207.                      rez = BULLET(&AP);
  208.                      if (rez==0)
  209.  
  210. /* data record has just been added and each index file has had a key
  211.    inserted pointing to this data record -- logically, the following
  212.    exists now:
  213.               <tag>  EMP_NO   LNAME     FNAME       SSN           ETC
  214.    in the DBF:  ' ','     1','Huth...','Cornel...','123456789\0','abc21_\0'
  215.  
  216.    in index 0:  1  (as a binary, 32-bit value, pointing to DBF record)
  217.    in index 1:  'Huth C6789'  (pointing to DBF record (no \0 in this case)
  218.  
  219.    '...' signify NULL bytes to end of field (set to NULL by memset())
  220.    the comma logically demarks the fields (there is no physical separator)
  221.    index 0 has a binary 0x00000001 value in it and points to the record added
  222.    index 1 has the 'Huth<space>C6789' in it and points to the record added
  223. */
  224.  
  225. /* note that below we use AP[0] when accessing via the first index file, and
  226.    AP[1] when accessing via the second -- this is not actually required
  227.    since the GET...XB routines are not transactioned-based, but it can be
  228.    convenient since many of the AP[]. members will already be setup -- below
  229.    we setup all members, even if already set, just for show */
  230.  
  231. /* AT THIS POINT, we have a single data record in the DBF, and a single
  232.    key in each of the index files that points to that record -- the
  233.    following show several _different_ methods of accessing this database: */
  234.  
  235. /* GETFIRSTXB grabs the first key in the index file and locates the data
  236.    record it is assigned to, returning both in dataRec and keyBuffer: */
  237.  
  238.                         AP[0].func = GETFIRSTXB;
  239.                         AP[0].handle = handleIndex0;
  240.                         AP[0].recPtr = &dataRec;
  241.                         AP[0].keyPtr = keyBuffer;
  242.                         rez = BULLET(&AP[0]);
  243.                         if (rez==0) {
  244.                            puts("GetFirstXB, index 0:");
  245.                            /* dataRec has DBF record data, keyBuffer has key of index file 1 */
  246.                         
  247.                            printf("recNo: %uh  tag: %c  emp#: %.6s  name: %s,%s  SSN: %s  misc: %s\n",
  248.                                 AP[0].recNo,
  249.                                 dataRec.tag,
  250.                                 dataRec.employeeNumber,
  251.                                 dataRec.lastName,dataRec.firstName,
  252.                                 dataRec.SSN,dataRec.andSoOn);
  253.                        
  254.                         }
  255.  
  256. /* as above, but using index file 1 to access the data file */
  257.  
  258.                         AP[1].func = GETFIRSTXB;
  259.                         AP[1].handle = handleIndex1;
  260.                         AP[1].recPtr = &dataRec;
  261.                         AP[1].keyPtr = keyBuffer;
  262.                         rez = BULLET(&AP[1]);
  263.                         if (rez==0) {
  264.                            puts("GetFirstXB, index 1:");
  265.                            /* dataRec has DBF record data, keyBuffer has key of index file 2 */
  266.                            printf("recNo: %uh  tag: %c  emp#: %.6s  name: %s,%s  SSN: %s  misc: %s\n",
  267.                                 AP[1].recNo,
  268.                                 dataRec.tag,
  269.                                 dataRec.employeeNumber,
  270.                                 dataRec.lastName,dataRec.firstName,
  271.                                 dataRec.SSN,dataRec.andSoOn);
  272.                         }
  273.  
  274. /* GETEQUALXB grabs the key that _EXACTLY_ matches the key you have placed in
  275.    keyBuffer[] -- if an exact match is not found, you can do a GETNEXTXB or a
  276.    GETPREVXB to locate the next/prev logical in-order key and record */
  277.  
  278. /* note that since index 1 is using binary key values, set the key to a
  279.    binary value -- if this index file allowed duplicates, you would also
  280.    need to specify the enumerator word (see [TBD] in the manual) */
  281.  
  282.                         *((long *)keyBuffer) = 1L;
  283.                         AP[0].func = GETEQUALXB;
  284.                         AP[0].handle = handleIndex0;
  285.                         AP[0].recPtr = &dataRec;
  286.                         AP[0].keyPtr = keyBuffer;
  287.                         rez = BULLET(&AP[0]);
  288.                         if (rez==0) {
  289.                            puts("GetEqualXB, key of (binary) 1, index 0:");
  290.                            /* dataRec has DBF record data, keyBuffer has key of index file 2 */
  291.                            printf("recNo: %uh  tag: %c  emp#: %.6s  name: %s,%s  SSN: %s  misc: %s\n",
  292.                                 AP[1].recNo,
  293.                                 dataRec.tag,
  294.                                 dataRec.employeeNumber,
  295.                                 dataRec.lastName,dataRec.firstName,
  296.                                 dataRec.SSN,dataRec.andSoOn);
  297.                         }
  298.                         else if (rez==1200) { /* 1200 is "KEY NOT FOUND" */
  299.                            puts("GetEqualXB, exact match not found, getting next...");
  300.                            /* if no exact match, perform a GETNEXTXB
  301.                               or GETPREVXB to find the logical next/prev key
  302.                               that _would_have_ preceded/followed the key
  303.                               you specified */
  304.  
  305.                            AP[0].func = GETNEXTXB;
  306.                            rez = BULLET(&AP[0]);
  307.                            if (rez==0) {
  308.                               puts("GetEqualXB+GetNextXB, key of (binary) 1, index 0:");
  309.                               /* dataRec has DBF record data, keyBuffer has key of index file 2 */
  310.                               printf("recNo: %uh  tag: %c  emp#: %.6s  name: %s,%s  SSN: %s  misc: %s\n",
  311.                                 AP[1].recNo,
  312.                                 dataRec.tag,
  313.                                 dataRec.employeeNumber,
  314.                                 dataRec.lastName,dataRec.firstName,
  315.                                 dataRec.SSN,dataRec.andSoOn);
  316.  
  317.                            }
  318.                         }
  319.                         else 
  320.                            puts("...other error");
  321.  
  322. /* as above, but using index file 2 to access the data file -- here we specify
  323.    that we want to locate to the first "H" in the index file (the two nulls
  324.    are added so that we are assured that we start at the very first "H", and
  325.    not "H<any-bytes>") -- there won't he an "H" only key, as expected, so we
  326.    do a GETNEXTXB to followup the request, thereby getting the first key that
  327.    starts with an H (so far, only "Huth C6789" exists anyway): */
  328.  
  329.                         strcpy(keyBuffer,"H\0\0");
  330.                         AP[1].func = GETEQUALXB;
  331.                         AP[1].handle = handleIndex1;
  332.                         AP[1].recPtr = &dataRec;
  333.                         AP[1].keyPtr = keyBuffer;
  334.                         rez = BULLET(&AP[1]);
  335.                         if (rez==1200) {  /* as expected, KEY NOT FOUND */
  336.                            AP[1].func = GETNEXTXB;
  337.                            rez = BULLET(&AP[1]);
  338.                            if (rez==0) {
  339.                               puts("GetEqualXB/GetNextXB, ('H' or greater), index 1:");
  340.                               /* dataRec has DBF record data, keyBuffer has key of index file 2 */
  341.                               printf("recNo: %uh  tag: %c  emp#: %.6s  name: %s,%s  SSN: %s  misc: %s\n",
  342.                                 AP[1].recNo,
  343.                                 dataRec.tag,
  344.                                 dataRec.employeeNumber,
  345.                                 dataRec.lastName,dataRec.firstName,
  346.                                 dataRec.SSN,dataRec.andSoOn);
  347.                            }
  348.                         }
  349.  
  350. /* AT THIS POINT, we can update the just gotten record and its related index
  351.    files, all with a single call, UpdateXB -- what we do here is change the
  352.    data record so that, in this example, both keys change, requiring Bullet
  353.    to update the index files and then update the data file -- all done
  354.    automatically -- EMP_NO is changed, as is SSN */
  355.  
  356. /* note that dataRec is already setup from previous work (the GETNEXTXB above)
  357.    and AP[1].recNo is also setup (see [TBD] in the manual) --
  358.    since AP[0].recNo is not necessarily set up, assign the known-to-be-it
  359.    record number in AP[1].recNo to AP[0].recNo */
  360.  
  361.                         strncpy(dataRec.employeeNumber,"     2",6);
  362.                         strcpy(dataRec.SSN,"123459876");
  363.  
  364. /* the above changes force both index files to update, as well as the DBF */
  365.  
  366.                         AP[0].func = UPDATEXB;
  367.                         AP[0].handle = handleIndex0;
  368.                         AP[0].recNo = AP[1].recNo;  /* from above call */
  369.                         AP[0].recPtr = &dataRec;
  370.                         AP[0].keyPtr = keyBuffer;
  371.                         AP[0].nextPtr = &AP[1];
  372.                         AP[1].func = UPDATEXB;
  373.                         AP[1].handle = handleIndex1;
  374.                         /* AP[1].recNo already setup from above */
  375.                         AP[1].recPtr = &dataRec;
  376.                         AP[1].keyPtr = keyBuffer;
  377.                         AP[1].nextPtr = NULL;
  378.                         rez = BULLET(&AP);
  379.                         if (rez==0) {
  380.                            /* since a transaction routine, must check
  381.                               first .stat for non-0 (error with data file) */
  382.                            if (AP[0].stat!=0) 
  383.                               puts("UpdateXB failed at record update");
  384.                            else
  385.                               puts("UpdateXB completed okay");
  386.                         }
  387.                         else {
  388.                            /* if non-0, rez is index of AP[] that failed
  389.                               -- rez-1 since rez returned as 1-based index */
  390.                            rez2 = AP[rez-1].stat;
  391.                            printf("UpdateXB failed, index: %uh, error: %u\n",(rez-1),rez2);
  392.                         }
  393.  
  394. /* Winding down this example...   */
  395. /* close up shop by closing files */
  396.  
  397.                         HP.func = CLOSEKXB;
  398.                         HP.handle = handleIndex1;
  399.                         rez = BULLET(&HP);
  400.                         if (rez!=0) 
  401.                            printf("closeKXB, index 1 failed: %u\n",rez);
  402.  
  403.                   }
  404.                   else   /* open ix1 */
  405.                      printf("openKXB failed, index 1, rez: %u\n",rez);
  406.                   
  407.  
  408.                   HP.func = CLOSEKXB;
  409.                   HP.handle = handleIndex0;
  410.                   rez = BULLET(&HP);
  411.                   if (rez!=0)
  412.                      printf("closeKXB, index 0 failed: %u\n",rez);
  413.  
  414.                }
  415.                else   /* open ix0 */
  416.                   printf("openKXB failed, index 0, rez: %u\n",rez);
  417.  
  418.             }
  419.             else   /* create ix1 */
  420.                printf("createKXB failed, index 1, rez: %u\n",rez);
  421.  
  422.          }
  423.          else   /* create ix0 */
  424.             printf("createKXB failed, index 0, rez: %u\n",rez);
  425.  
  426.       }
  427.       else   /* open DBF */
  428.          printf("openDXB failed, rez: %u\n",rez);
  429.  
  430.    }
  431.    else   /* create DBF */
  432.       printf("createDXB failed, rez: %u\n",rez);
  433.  
  434.  
  435.    EP.func = EXITXB;
  436.    rez = BULLET(&EP);
  437. }
  438. else   /* init */
  439.    printf("initXB failed, rez: %u\n",rez);
  440.  
  441.  
  442. return(0);
  443. }
  444. /* program exit */
  445.